const express = require('express');
const axios = require('axios');

// 配置节点信息
const NODES = [
  { id: 1, port: 3001, host: 'localhost' },
  { id: 2, port: 3002, host: 'localhost' },
  { id: 3, port: 3003, host: 'localhost' }
];

// 获取当前节点配置
const NODE_ID = parseInt(process.env.NODE_ID || '1');
const PORT = NODES[NODE_ID - 1].port;

// 内存存储
const cache = new Map();

// 一致性哈希函数
function getNodeId(key) {
  let hash = 0;
  for (let i = 0; i < key.length; i++) {
    const char = key.charCodeAt(i);
    hash = ((hash << 5) - hash) + char;
    hash = hash & hash; // 转换为32位整数
  }
  return Math.abs(hash) % NODES.length + 1;
}

// 获取目标节点
function getTargetNode(key) {
  const nodeId = getNodeId(key);
  return NODES.find(node => node.id === nodeId);
}

// 创建Express应用
const app = express();
app.use(express.json());

// 健康检查接口
app.get('/health', (req, res) => {
  res.json({ status: 'ok', nodeId: NODE_ID, port: PORT });
});

// 写入/更新缓存
app.post('/', async (req, res) => {
  try {
    const keys = Object.keys(req.body);
    if (keys.length !== 1) {
      return res.status(400).json({ error: '每次请求只支持一个key' });
    }
    
    const key = keys[0];
    const value = req.body[key];
    const targetNode = getTargetNode(key);
    
    if (targetNode.id === NODE_ID) {
      // 数据存储在当前节点
      cache.set(key, value);
      console.log(`[Node${NODE_ID}] 本地存储: ${key}=${JSON.stringify(value)}`);
      res.json({ success: true, node: NODE_ID });
    } else {
      // 转发到目标节点
      const url = `http://${targetNode.host}:${targetNode.port}/`;
      console.log(`[Node${NODE_ID}] 转发到 Node${targetNode.id}: ${key}`);
      
      try {
        const response = await axios.post(url, { [key]: value });
        res.json({ success: true, forwarded: true, node: targetNode.id });
      } catch (error) {
        console.error(`转发失败: ${error.message}`);
        res.status(500).json({ error: '转发失败' });
      }
    }
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// 读取缓存
app.get('/:key', async (req, res) => {
  try {
    const key = req.params.key;
    const targetNode = getTargetNode(key);
    
    if (targetNode.id === NODE_ID) {
      // 数据在当前节点
      if (cache.has(key)) {
        const value = cache.get(key);
        console.log(`[Node${NODE_ID}] 本地读取: ${key}=${JSON.stringify(value)}`);
        res.json({ [key]: value });
      } else {
        console.log(`[Node${NODE_ID}] 本地未找到: ${key}`);
        res.status(404).send();
      }
    } else {
      // 从目标节点获取
      const url = `http://${targetNode.host}:${targetNode.port}/${encodeURIComponent(key)}`;
      console.log(`[Node${NODE_ID}] 从 Node${targetNode.id} 获取: ${key}`);
      
      try {
        const response = await axios.get(url);
        res.json(response.data);
      } catch (error) {
        if (error.response && error.response.status === 404) {
          res.status(404).send();
        } else {
          console.error(`获取失败: ${error.message}`);
          res.status(500).json({ error: '获取失败' });
        }
      }
    }
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// 删除缓存
app.delete('/:key', async (req, res) => {
  try {
    const key = req.params.key;
    const targetNode = getTargetNode(key);
    
    if (targetNode.id === NODE_ID) {
      // 数据在当前节点
      const deleted = cache.delete(key);
      console.log(`[Node${NODE_ID}] 本地删除: ${key}, 结果: ${deleted}`);
      res.json({ deleted: deleted ? 1 : 0 });
    } else {
      // 转发删除请求到目标节点
      const url = `http://${targetNode.host}:${targetNode.port}/${encodeURIComponent(key)}`;
      console.log(`[Node${NODE_ID}] 转发删除到 Node${targetNode.id}: ${key}`);
      
      try {
        const response = await axios.delete(url);
        res.json(response.data);
      } catch (error) {
        console.error(`删除失败: ${error.message}`);
        res.status(500).json({ error: '删除失败' });
      }
    }
  } catch (error) {
    res.status(500).json({ error: error.message });
  }
});

// 启动服务器
app.listen(PORT, () => {
  console.log(`分布式缓存节点 ${NODE_ID} 启动成功`);
  console.log(`监听端口: ${PORT}`);
  console.log(`节点列表:`, NODES);
  console.log(`\n使用示例:`);
  console.log(`curl -XPOST -H "Content-type: application/json" http://localhost:${PORT}/ -d '{"myname": "电子科技大学@2023"}'`);
  console.log(`curl http://localhost:${PORT}/myname`);
  console.log(`curl -XDELETE http://localhost:${PORT}/myname`);
});

// 导出供测试使用
module.exports = { app, getNodeId, NODES };
